package com.cmw.auntapp.core.util;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.cmw.auntapp.R;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

import static com.cmw.auntapp.constant.Constant.HTTP_CONNECT_TIME_OUT_KEY;
import static com.cmw.auntapp.constant.Constant.HTTP_READ_TIME_OUT_KEY;
import static com.cmw.auntapp.constant.Constant.HTTP_WRITE_TIME_OUT_KEY;

public class HttpUtil {
    public static final String TAG = "HttpUtil";

    static Context context;

    private static boolean isNetworkAvailable(){
        if(null == context){
            Log.e(TAG,"在调用 isNetworkAvailable 方法时，必须传入 context 对象");
            return false;
        }
        if(NetworkAvailableUtils.isNetworkAvailable(context)){
            return true;
        }else{
            Log.e(TAG,"当前设备网络未连接，请检查设备WIFI 或 3/4G 是否打开并能连网！");
            return false;
        }
    }
    /**
     * POST异步提交数据
     */
    public static String post(String url, Map<String,String> params, Callback callback) {
       return post(url, null, params, callback);
    }
    /**
     * POST异步提交数据
     */
    public static String post(String url, Map<String,String> head,
                             Map<String,String> params, Callback callback) {
        if(!isNetworkAvailable()) return context.getResources().getString(R.string.un_join_network_err);
        OkHttpClient client = getOkHttpClient(head);

        Request.Builder builder=new Request.Builder().url(url);

        JSONObject debugJson = new JSONObject();
        Map<String,String> headMap = new HashMap<>();
        Map<String,String> paramsMap = new HashMap<>();
        debugJson.put("url", url);
        debugJson.put("method", "POST");
        debugJson.put("headers", headMap);
        debugJson.put("params", paramsMap);

        if(head!=null&&head.size()>0){
            for (Map.Entry<String, String> entry : head.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                headMap.put(key, val);
                builder.addHeader(key,val);
            }
        }

        FormBody.Builder formBody = new FormBody.Builder();
        if(params!=null && params.size()>0){
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                paramsMap.put(key, val);
                formBody.add(entry.getKey(),entry.getValue());
            }
        }
        Log.d(TAG, debugJson.toJSONString());
        RequestBody requestBody = formBody.build();
        Request request=builder.post(requestBody).build();
        client.newCall(request).enqueue(callback);
        return null;
    }

    /**
     * POST异步提交数据
     */
    public static <T> String post(String url, Map<String,String> head,
                            T requestData, Callback callback) {
        if(!isNetworkAvailable()) return context.getResources().getString(R.string.un_join_network_err);
        OkHttpClient client = getOkHttpClient(head);
        Request.Builder builder=new Request.Builder().url(url);

        JSONObject debugJson = new JSONObject();
        Map<String,String> headMap = new HashMap<>();
        debugJson.put("url", url);
        debugJson.put("method", "POST");
        debugJson.put("headers", headMap);

        if(head!=null&&head.size()>0){
            for (Map.Entry<String, String> entry : head.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                headMap.put(key, val);
                builder.addHeader(key,val);
            }
        }
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式，
        String requestBodyData = FastJsonUtil.convertJsonToStr(requestData);
        debugJson.put("requestBodyData", requestBodyData);
        Log.d(TAG, debugJson.toJSONString());
        RequestBody requestBody = RequestBody.create(JSON, requestBodyData);
        Request request=builder.post(requestBody).build();
        client.newCall(request).enqueue(callback);
        return null;
    }

    /**
     * Delete 异步删除数据
     */
    public static String delete(String url, Map<String,String> head,
                           Map<String,String> params, Callback callback) {
       return request(url, head, params, callback, "DELETE");
    }

    /**
     * PUT异步修改数据
     */
    public static void put(String url, Map<String,String> params, Callback callback) {
        request(url, null, params, callback, "PUT");
    }

    /**
     * PUT异步修改数据
     */
    public static String put(String url, Map<String,String> head,
                            Map<String,String> params, Callback callback) {
       return request(url, head, params, callback, "PUT");
    }

    public static String request(String url, Map<String,String> head,
                               Map<String,String> params, Callback callback, String method){
        if(!isNetworkAvailable()) return context.getResources().getString(R.string.un_join_network_err);
        if(StringUtils.isEmpty(method) || method.equals("GET")){
            get(url, head, params, callback);
            return null;
        }
        JSONObject debugJson = new JSONObject();
        Map<String,String> headMap = new HashMap<>();
        Map<String,String> paramsMap = new HashMap<>();
        debugJson.put("url", url);
        debugJson.put("method", method);
        debugJson.put("headers", headMap);
        debugJson.put("params", paramsMap);
        OkHttpClient client = getOkHttpClient(head);
        Request.Builder builder=new Request.Builder().url(url);
        if(head!=null&&head.size()>0){
            for (Map.Entry<String, String> entry : head.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                headMap.put(key, val);
                builder.addHeader(key,val);
            }
        }

        FormBody.Builder formBody = new FormBody.Builder();
        if(params!=null && params.size()>0){
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                paramsMap.put(key,val);
                formBody.add(entry.getKey(),entry.getValue());
            }
        }
        Log.d(TAG, debugJson.toJSONString());
        method = method.toUpperCase();
        RequestBody requestBody = formBody.build();
        Request request =  builder.method(method, requestBody).build();
        client.newCall(request).enqueue(callback);
        return null;
    }

    /**
     * GET 请求数据
     */
    public static String get(String url, Callback callback) {
       return get(url, null, null, callback);
    }

    /**
     * 文件上传
     * @param url 文件上传地址
     * @param headers 请求头
     * @param params    请求参数
     * @param file  要上传的文件对象
     * @param progressListener  进度监听事件
     * @param callback  上传完成后的回调
     */
    public static void uploadFile(String url, Map<String, String> headers, Map<String,String> params, File file, ProgressRequestBody.ProgressListener progressListener, Callback callback) {
        MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                //.addFormDataPart("intro", intro) // 提交内容字段
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("*/*"), file)); // 第一个参数传到服务器的字段名，第二个你自己的文件名，第三个MediaType.parse("*/*")和我们之前说的那个type其实是一样的
        ProgressRequestBody requestBody = new ProgressRequestBody(builder.build(), progressListener);

        uploadFile(url, headers, params, requestBody, callback);
    }

    /**
     * 文件下传
     * 参考：https://blog.csdn.net/weixin_38629529/article/details/90052650
     *      http://www.daokeyou.top/detail/8FA4FFF6101437CD1EC12A7A6EC0BA1B
     * @param url
     * @param headers
     * @param requestBody
     * @param callback
     */
    public static void uploadFile(String url, Map<String, String> headers, Map<String,String> params, RequestBody requestBody, Callback callback) {
        OkHttpClient client = getOkHttpClient(headers);
        url  = getParsUrl(url, params);
        Request.Builder builder=new Request.Builder().url(url);
        addHeaders(headers, builder);
        Request request = builder.post(requestBody).build();
        client.newCall(request).enqueue(callback);
    }

    /**
     * GET 请求数据
     */
    public static void getWithHeaders(String url, Map<String,String> head, Callback callback) {
        get(url, head, null, callback);
    }
    /**
     * GET 请求数据
     */
    public static void get(String url, Map<String,String> params, Callback callback) {
        get(url, null, params, callback);
    }

    /**
     * GET 请求数据
     */
    public static String get(String url, Map<String,String> head,
                            Map<String,String> params, Callback callback) {
        if(!isNetworkAvailable()) return context.getResources().getString(R.string.un_join_network_err);
        OkHttpClient client = getOkHttpClient(head);

        String gurl = getParsUrl(url, params);
      //  Log.i(TAG, "url="+gurl);

        JSONObject debugJson = new JSONObject();
        Map<String,String> headMap = new HashMap<>();
        debugJson.put("url", url);
        debugJson.put("method", "GET");
        debugJson.put("headers", head);
        debugJson.put("params", params);


        Request.Builder builder=new Request.Builder().url(gurl);
        addHeaders(head, builder);
        Log.d(TAG, debugJson.toJSONString());
        Request request=builder.get().build();
        client.newCall(request).enqueue(callback);
        return null;
    }

    private static OkHttpClient getOkHttpClient(Map<String,String> head) {
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        if (null == head || head.isEmpty()) {
            return clientBuilder.build();
        }
        String connectTimeOutStr = head.get(HTTP_CONNECT_TIME_OUT_KEY);
        String readTimeOutStr = head.get(HTTP_READ_TIME_OUT_KEY);
        String writeTimeOutStr = head.get(HTTP_WRITE_TIME_OUT_KEY);
        if (!TextUtils.isEmpty(connectTimeOutStr)) { // 在请求头中可以设置 Http 连接超时时间
            clientBuilder
                    .connectTimeout(Integer.parseInt(connectTimeOutStr), TimeUnit.SECONDS);
        }
        if (!TextUtils.isEmpty(readTimeOutStr)) { // 在请求头中可以设置 Http 请求超时时间
            clientBuilder
                    .readTimeout(Integer.parseInt(readTimeOutStr), TimeUnit.SECONDS);
        }
        if (!TextUtils.isEmpty(writeTimeOutStr)) { // 在请求头中可以设置 Http 请求超时时间
            clientBuilder
                    .writeTimeout(Integer.parseInt(writeTimeOutStr), TimeUnit.SECONDS);
        }
        return clientBuilder.build();
    }

    private static void addHeaders(Map<String, String> head, Request.Builder builder) {
        if(head != null && head.size() > 0){
            for (Map.Entry<String, String> entry : head.entrySet()) {
                String key = entry.getKey();
                String val = entry.getValue();
                builder.addHeader(key,val);
            }
        }
    }


    private static String getParsUrl(String url , Map<String, String> params){
        StringBuilder sb = new StringBuilder();
        if(null == params || params.size() == 0) return url;

        Set<String> keys = params.keySet();
        int index = 0;
        for(String key : keys){
            String sign = "&";
            if(index == 0){
                if(url.indexOf("?") == -1){
                    sign = "?";
                }
            }
            String val = params.get(key);
            if(null == val) val = "";
            sb.append(sign).append(key).append("=").append(val);
            index++;
        }
        return url+sb.toString();
    }

    public static void setContext(Context mContext) {
        context = mContext;
    }
}
